package view.lcdui;

import java.util.Vector;

import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.List;

/**
 * A Decorator List class to add pagination through itens
 * without state loss
 *
 * Based on the article "Big designs for small devices" 
 * @author Marcelo Gatto
 */
public class PagableList extends List implements CommandListener {

	public final static Command NEXT_COMMAND  = new Command("Next",  Command.SCREEN, 1);
	public final static Command PREV_COMMAND  = new Command("Prev",	 Command.SCREEN, 1);

	private Vector strList = new Vector();
	private Vector imgList = new Vector();
	private boolean[] listState;

	private int maxPerPage = 5; /* default */
	private int current = 0;
	private int listType;
	
	private CommandListener userCmdListener = null;

	public PagableList(String title, int listType) {
		super(title, listType);
		this.listType = listType;
		super.setCommandListener(this);
	}

	public PagableList(String title, int listType, String[] strElements, Image[] imgElements) {
		this(title, listType);
		if(imgElements==null) imgElements = new Image[strElements.length];
		for(int i=0; i<strElements.length; i++) append(strElements[i], imgElements[i]);
	}

	private void addCommands() {
		if(current+maxPerPage<size())
			 super.addCommand(NEXT_COMMAND);
		else super.removeCommand(NEXT_COMMAND);
		
		if(current!=0)
			 super.addCommand(PREV_COMMAND);
		else super.removeCommand(PREV_COMMAND);
	}

	/**
	 * Set how many itens will be show at each page
	 */
	public void setMaxPerPage(int max) {
		maxPerPage = max;
	}
	
	/**
	 * Get all selected itens
	 */
	public String[] getAllSelected() {
		Vector v_selected = new Vector();
		for(int i=0; i<listState.length; i++) {
			if(listState[i]) v_selected.addElement( getString(i) );
		}
		String[] s_selected = new String[v_selected.size()];
		v_selected.copyInto(s_selected);
		return s_selected;
	}

	public int append(String str, Image img) {
		strList.addElement(str);
		imgList.addElement(img);
		addCommands();
		if(current+maxPerPage > strList.size()-1) {
			super.append(str, img);
		}
		return strList.size() - 1;
	}

	public void delete(int elementNum) {
		strList.removeElementAt(elementNum);
		imgList.removeElementAt(elementNum);
		update();
	}

	public void insert(int elementNum, String str, Image img) {
		strList.insertElementAt(str, elementNum);
		imgList.insertElementAt(img, elementNum);
		update();
	}

	public void set(int elementNum, String str, Image img) {
		strList.setElementAt(str, elementNum);
		imgList.setElementAt(img, elementNum);
		update();
	}

	public int size() {
		return strList.size();
	}

	public Image getImage(int elementNum) {
		return (Image) imgList.elementAt(elementNum);
	}
	
	public String getString(int elementNum) {
		return (String) strList.elementAt(elementNum);
	}

	public int getSelectedIndex() {
		int i = super.getSelectedIndex();
		return i == -1 ? -1 : current+1;
	}

	 public boolean isSelected(int elementNum) {
	    return listState[elementNum];
	 }
	 
	public void setCommandListener(CommandListener cmd) {
		userCmdListener = cmd;
	}
	
	private void saveState() {
		if(listState==null || listType==List.IMPLICIT || listType==List.EXCLUSIVE)
			listState = new boolean[size()];
		else if(listState.length<size()) { // item appended
			boolean bkup[] = listState;
			listState = new boolean[size()];
			for(int i=0; i<bkup.length; i++) listState[i] = bkup[i];
		}
		boolean[] flag = new boolean[super.size()];
		super.getSelectedFlags(flag);
		for(int i=0; i<flag.length; i++) {
			listState[i+current] = flag[i];
		}
	}
	
	private void update() {
		deleteAll();
		for (int i=current; i < current + maxPerPage; i++) {
			if(i>=strList.size()) break;
			int pos = super.append((String) strList.elementAt(i), (Image) imgList.elementAt(i));
			if(listState!=null && listState[i]) super.setSelectedIndex(pos, true);
		}
		addCommands();
	}

	public void commandAction(Command cmd, Displayable display) {	
		saveState();
		
		if(cmd == NEXT_COMMAND)      current = Math.min(current+maxPerPage, strList.size()-1);
		else if(cmd == PREV_COMMAND) current = Math.max(current-maxPerPage, 0);
		else {
			if(userCmdListener!=null) userCmdListener.commandAction(cmd, display);
			return;
		}
		
		update();
	}
}